package singleton

import (
	"errors"
	"fmt"
	"sync"
)

type IBeanContainer interface {
	GetBean(string) (bool, interface{})
	SetBean(string, interface{}) error
}

type tBeanContainer struct {
	mBeans map[string]interface{}
	mRWMutex *sync.RWMutex
}

func newBeanContainer() *tBeanContainer {
	return &tBeanContainer{
		mBeans: make(map[string]interface{}, 16),
		mRWMutex: new(sync.RWMutex),
	}
}

func (me *tBeanContainer) GetBean(name string) (bool, interface{}) {
	me.mRWMutex.RLock()
	defer me.mRWMutex.RUnlock()

	it, ok := me.mBeans[name]
	if ok {
		return true, it
	} else {
		return false, nil
	}
}

func (me *tBeanContainer) SetBean(name string, it interface{}) error {
	me.mRWMutex.Lock()
	defer me.mRWMutex.Unlock()

	if _,ok := me.mBeans[name];ok {
		return errors.New(fmt.Sprintf("bean with name %s already exists", name))
	}

	me.mBeans[name] = it
	return nil
}

type tContainedSingleton struct {}

func (me *tContainedSingleton) Hello() {
	fmt.Printf("tContainedSingleton.Hello\n")
}

func newContainedSingleton() IDemoSingleton {
	return &tContainedSingleton{}
}


var DefaultBeanContaibner = newBeanContainer()

func init() {
	DefaultBeanContaibner.SetBean("IDemoSingleton", newContainedSingleton())
}